package io.github.codelifeleno.jdbrelease.util;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class CollectionToMapConverter {

    /**
     * 将集合转换为Map，使用对象属性作为键
     * <pre>{@code
     * List<Person> people = Arrays.asList(
     *                 new Person("1", "Alice"),
     *                 new Person("2", "Bob"),
     *                 new Person("1", "Charlie") // 重复的ID
     *         );
     *
     *         // 基础转换（自动覆盖重复键）
     *         Map<String, Person> idMap = CollectionToMapConverter.toMap(
     *                 people,
     *                 Person::getId
     *         );
     * }</pre>
     *
     * @param collection   原始集合
     * @param keyExtractor 键提取函数
     * @param <T>          集合元素类型
     * @param <K>          键类型
     * @return 转换后的Map
     */
    public static <T, K> Map<K, T> toMap(
            Collection<T> collection,
            Function<T, K> keyExtractor) {
        return toMap(collection, keyExtractor, (existing, replacement) -> replacement);
    }

    /**
     * 带冲突处理的版本
     * <pre>{@code
     * List<Person> people = Arrays.asList(
     *                 new Person("1", "Alice"),
     *                 new Person("2", "Bob"),
     *                 new Person("1", "Charlie") // 重复的ID
     *         );
     *
     *         // 带冲突处理的版本
     *         Map<String, Person> idMap1 = CollectionToMapConverter.toMap(
     *                 people,
     *                 Person::getId,(k,v)-> {
     *                     System.out.println(k + "=" + v);
     *                     return k;
     *                 }
     *         );
     * }</pre>
     *
     * @param mergeFunction 冲突处理函数，返回最终保留的值
     */
    public static <T, K> Map<K, T> toMap(
            Collection<T> collection,
            Function<T, K> keyExtractor,
            MergeFunction<T> mergeFunction) {
        return collection.stream()
                .collect(Collectors.toMap(
                        keyExtractor,
                        Function.identity(),
                        mergeFunction::apply,
                        LinkedHashMap::new // 保持插入顺序
                ));
    }

    /**
     * 将集合转换为Map，使用对象属性作为键和值
     * <pre>{@code
     * List<Product> products = Arrays.asList(
     *      new Product("P001", "Laptop", 999.99),
     *      new Product("P002", "Phone", 699.99),
     *      new Product("P001", "Laptop Pro", 1299.99) // 重复ID
     * );
     *
     * // 基础转换（ID -> Name）
     * Map<String, String> nameMap = CollectionToMapConverter.toMap(
     *      products,
     *      Product::getId,
     *      Product::getName
     * );
     * }</pre>
     *
     * @param collection     原始集合
     * @param keyExtractor   键提取函数
     * @param valueExtractor 值提取函数
     * @param <T>            集合元素类型
     * @param <K>            键类型
     * @param <V>            值类型
     * @return 转换后的Map
     */
    public static <T, K, V> Map<K, V> toMap(
            Collection<T> collection,
            Function<T, K> keyExtractor,
            Function<T, V> valueExtractor) {
        return toMap(collection, keyExtractor, valueExtractor, (e, r) -> r);
    }

    /**
     * 带冲突处理的版本
     * <pre>{@code
     * List<Product> products = Arrays.asList(
     *      new Product("P001", "Laptop", 999.99),
     *      new Product("P002", "Phone", 699.99),
     *      new Product("P001", "Laptop Pro", 1299.99) // 重复ID
     * );
     *
     * // 带冲突处理的版本（ID -> Price）
     *         Map<String, Double> priceMap = CollectionToMapConverter.toMap(
     *                 products,
     *                 Product::getId,
     *                 Product::getPrice,
     *                 (a, b) -> {
     *                     return a;
     *                 }
     *         );
     * );
     * }</pre>
     * @param mergeFunction 冲突处理函数，返回最终保留的值
     */
    public static <T, K, V> Map<K, V> toMap(
            Collection<T> collection,
            Function<T, K> keyExtractor,
            Function<T, V> valueExtractor,
            MergeFunction<V> mergeFunction) {
        return collection.stream()
                .collect(Collectors.toMap(
                        keyExtractor,
                        valueExtractor,
                        mergeFunction::apply,
                        LinkedHashMap::new
                ));
    }

    /**
     * 合并函数接口
     */
    @FunctionalInterface
    public interface MergeFunction<T> {
        T apply(T existing, T replacement);
    }

}